//Alex Silkin
#include "KitRobotTest.h"
#include <iostream>
#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "PartRobotAgentMock.h"
#include "ConveyorAgentMock.h"
#include "Table.h"
#include "InspectorAgentMock.h"

#include <qpoint.h>

#include "KitRobotAgentMock.h"

using ::testing::Return;

//init test
KitRobotTest::KitRobotTest() : kitRobot("Kit Robot Test") {

}

  void KitRobotTest::SetUp() {
	 this->kitRobot.SetGui(&gui);

	table = new Table();

	this->kitRobot.SetPartsRobot(&partsRobot);
	this->kitRobot.SetOnConveyor(&onConveyor);
	this->kitRobot.SetOffBadConveyor(&offBadConveyor);
	this->kitRobot.SetOffGoodConveyor(&offGoodConveyor);
	this->kitRobot.SetTable(table);
	this->kitRobot.SetInspector(&inspector);

	testing::DefaultValue<QPoint>::Set(QPoint(0,0));
	ON_CALL(onConveyor, getPickUpKitPosition()).WillByDefault(Return(QPoint(0,0)));
	ON_CALL(offBadConveyor, getDropOffKitPosition()).WillByDefault(Return(QPoint(0,0)));
	ON_CALL(offGoodConveyor, getDropOffKitPosition()).WillByDefault(Return(QPoint(0,0)));


	/*ON_CALL(gui, DoGoToNeutralPosition()).WillByDefault(Return(NULL));
	ON_CALL(gui, DoGoToDestination(QPoint(0,0))).WillByDefault(Return(NULL));
	ON_CALL(gui, DoPickUpKit(makeNewKit())).WillByDefault(Return(NULL));
	ON_CALL(gui, DoDropOffKit()).WillByDefault(Return(NULL));

	ON_CALL(inspector, msgInspectKit()).WillByDefault(Return(NULL));*/
  }

 Kit* KitRobotTest::makeNewKit() {
	Kit* kit = new Kit();
	return kit;
 }

bool KitRobotTest::runScheduler() {
	return kitRobot.pickAndExecuteAnAction();
}

bool KitRobotTest::isAllReferencesInitialized() {
	if(kitRobot.GetOnConveyor() == NULL || kitRobot.GetOffBadConveyor() == NULL || kitRobot.GetOffGoodConveyor() == NULL || kitRobot.GetInspector() == NULL || kitRobot.GetTable() == NULL || kitRobot.GetInspector() == NULL || kitRobot.GetGui() == NULL)
		return false;
	return true;
}

void KitRobotTest::sleep(unsigned int mseconds)
{
    clock_t goal = mseconds + clock();
    while (goal > clock());
}

TEST_F(KitRobotTest, InitializationTest){
		EXPECT_TRUE(isAllReferencesInitialized());
}


TEST_F(KitRobotTest, InitialSchedulerTest){
		EXPECT_FALSE(runScheduler());
}
//
//TEST_F(KitRobotTest, TableSlotsFullAwakeScheduleTest) {
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//	EXPECT_FALSE(runScheduler());
//
//	kitRobot.GetTable()->insert(this->makeNewKit(), 0);
//	kitRobot.GetTable()->insert(this->makeNewKit(), 1);
//
//	Kit* kitToMake = this->makeNewKit();
//
//	kitRobot.msgHereIsKit(kitToMake);
//
//	EXPECT_FALSE(runScheduler());
//	EXPECT_TRUE(kitRobot.GetAwakeScheduled());
//
//	this->sleep(500);
//
//	EXPECT_FALSE(runScheduler());
//	EXPECT_TRUE(kitRobot.GetAwakeScheduled());
//	
//	this->sleep(5000);
//
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//
//	this->sleep(500);
//
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//
//
//	kitRobot.GetTable()->insert(kitRobot.GetTable()->remove(1), 2);
//
//	kitRobot.msgAnimationDone();
//	kitRobot.msgAnimationDone();
//	kitRobot.msgAnimationDone();
//	kitRobot.msgAnimationDone();
//	kitRobot.msgAnimationDone();
//
//	EXPECT_TRUE(runScheduler());
//
//
//	EXPECT_FALSE(runScheduler());
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//
//
//	kitRobot.msgKitFinished(kitRobot.GetTable()->peek(0));
//	EXPECT_FALSE(runScheduler());
//	EXPECT_TRUE(kitRobot.GetAwakeScheduled());
//
//	this->sleep(50);
//
//	EXPECT_TRUE(kitRobot.GetAwakeScheduled());
//
//	EXPECT_FALSE(runScheduler());
//
//	this->sleep(5000);
//
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//
//	this->sleep(500);
//
//	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
//
//
//	EXPECT_FALSE(runScheduler());
//	EXPECT_TRUE(kitRobot.GetAwakeScheduled());
//}

TEST_F(KitRobotTest, PuttingKitOnTableTest){
		EXPECT_FALSE(kitRobot.GetAwakeScheduled());
		EXPECT_FALSE(runScheduler());

		kitRobot.GetTable()->remove(0);
		kitRobot.GetTable()->remove(1);
		kitRobot.GetTable()->remove(2);

		kitRobot.GetTable()->insert(this->makeNewKit(), 0);
		

		EXPECT_TRUE(kitRobot.GetTable()->peek(0) != NULL);
		EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
		EXPECT_TRUE(kitRobot.GetTable()->peek(2) == NULL);

		Kit* kitToMake = this->makeNewKit();

		kitRobot.msgHereIsKit(kitToMake);

		EXPECT_CALL(this->onConveyor, getPickUpKitPosition());
		EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0))).Times(2);
		EXPECT_CALL(this->gui, DoPickUpKit(kitToMake));
		EXPECT_CALL(this->onConveyor, msgKitPickedUp());
		EXPECT_CALL(this->gui, DoDropOffKit());
		EXPECT_CALL(this->gui, DoGoToNeutralPosition());
		EXPECT_CALL(this->partsRobot, msgMakeKit(kitToMake));

		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();

		EXPECT_TRUE(runScheduler());

		EXPECT_TRUE(kitRobot.GetTable()->peek(0) != NULL);
		EXPECT_EQ(kitRobot.GetTable()->peek(1) , kitToMake);
		EXPECT_TRUE(kitRobot.GetTable()->peek(2) == NULL);
		
		EXPECT_FALSE(runScheduler());
}

TEST_F(KitRobotTest, GivingKitToInspectorTest) {
		EXPECT_FALSE(kitRobot.GetAwakeScheduled());
		EXPECT_FALSE(runScheduler());

		Kit* kitToMake = this->makeNewKit();

		kitRobot.GetTable()->remove(0);
		kitRobot.GetTable()->remove(1);
		kitRobot.GetTable()->remove(2);

		kitRobot.GetTable()->insert(kitToMake, 0);
		

		EXPECT_EQ(kitRobot.GetTable()->peek(0), kitToMake);
		EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
		EXPECT_TRUE(kitRobot.GetTable()->peek(2) == NULL);

		kitRobot.msgKitFinished(kitToMake);

		EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0))).Times(2);
		//EXPECT_CALL(this->gui, DoGoToDestination(table->getTableSlotPosition(0)));
		EXPECT_CALL(this->gui, DoPickUpKit(kitToMake));
		//EXPECT_CALL(this->gui, DoGoToDestination(table->getTableSlotPosition(2)));
		EXPECT_CALL(this->gui, DoDropOffKit());
		EXPECT_CALL(this->gui, DoGoToNeutralPosition());
		EXPECT_CALL(this->inspector, msgInspectKit());

		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();
		kitRobot.msgAnimationDone();

		EXPECT_TRUE(runScheduler());


		EXPECT_TRUE(kitRobot.GetTable()->peek(0) == NULL);
		EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
		EXPECT_EQ(kitRobot.GetTable()->peek(2), kitToMake);


		EXPECT_FALSE(runScheduler());
}

TEST_F(KitRobotTest, GivingGoodKitToOffGoodConveyorTest) {

	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
	EXPECT_FALSE(runScheduler());

	Kit* kitToMake = this->makeNewKit();

	kitRobot.GetTable()->remove(0);
	kitRobot.GetTable()->remove(1);
	kitRobot.GetTable()->remove(2);
	kitRobot.GetTable()->insert(kitToMake, 2);

	EXPECT_TRUE(kitRobot.GetTable()->peek(0) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
	EXPECT_EQ(kitRobot.GetTable()->peek(2) , kitToMake);

	kitRobot.msgHereIsKitState(Good);

	EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0))).Times(2);
	//EXPECT_CALL(this->gui, DoGoToDestination(table->getTableSlotPosition(2)));
	EXPECT_CALL(this->gui, DoPickUpKit(kitToMake));
	EXPECT_CALL(this->offGoodConveyor, getDropOffKitPosition());
	//EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0)));
	EXPECT_CALL(this->gui, DoDropOffKit());
	EXPECT_CALL(this->gui, DoGoToNeutralPosition());
	EXPECT_CALL(this->offGoodConveyor, msgHereIsFinishedKit(kitToMake));

	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();

	EXPECT_TRUE(runScheduler());

	EXPECT_TRUE(kitRobot.GetTable()->peek(0) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(2) == NULL);
	
	EXPECT_FALSE(runScheduler());
}

TEST_F(KitRobotTest, GivingBadKitToOffBadConveyorTest) {

	EXPECT_FALSE(kitRobot.GetAwakeScheduled());
	EXPECT_FALSE(runScheduler());

	Kit* kitToMake = this->makeNewKit();

	kitRobot.GetTable()->remove(0);
	kitRobot.GetTable()->remove(1);
	kitRobot.GetTable()->remove(2);
	kitRobot.GetTable()->insert(kitToMake, 2);

	EXPECT_TRUE(kitRobot.GetTable()->peek(0) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
	EXPECT_EQ(kitRobot.GetTable()->peek(2) , kitToMake);

	kitRobot.msgHereIsKitState(Bad);

	EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0))).Times(2);
	//EXPECT_CALL(this->gui, DoGoToDestination(table->getTableSlotPosition(2)));
	EXPECT_CALL(this->gui, DoPickUpKit(kitToMake));
	EXPECT_CALL(this->offBadConveyor, getDropOffKitPosition());
	//EXPECT_CALL(this->gui, DoGoToDestination(QPoint(0,0)));
	EXPECT_CALL(this->gui, DoDropOffKit());
	EXPECT_CALL(this->gui, DoGoToNeutralPosition());
	EXPECT_CALL(this->offBadConveyor, msgHereIsFinishedKit(kitToMake));

	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();
	kitRobot.msgAnimationDone();

	EXPECT_TRUE(runScheduler());

	EXPECT_TRUE(kitRobot.GetTable()->peek(0) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(1) == NULL);
	EXPECT_TRUE(kitRobot.GetTable()->peek(2) == NULL);
	
	EXPECT_FALSE(runScheduler());
}
